package com.example.caoben_back.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.caoben_back.entity.po.ProvinceWeather;
import com.example.caoben_back.mapper.ProvinceWeatherMapper;
import com.example.caoben_back.service.IProvinceWeatherService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.caoben_back.utils.RedisUtil;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 各省份天气信息表 服务实现类
 * </p>
 *
 * @author ylsink
 * @since 2025-11-11
 */
@Service
public class ProvinceWeatherServiceImpl extends ServiceImpl<ProvinceWeatherMapper, ProvinceWeather> implements IProvinceWeatherService {
    @Resource
    private ProvinceWeatherMapper weatherMapper;
    
    @Resource
    private RestTemplate restTemplate;
    
    @Resource
    private RedisUtil redisUtil;
    
    private final ObjectMapper objectMapper = new ObjectMapper();
    private final String GAODE_KEY = "7ad4bddca5b6def617eaf473d5f6c0ed"; // 高德API密钥
    private final long EXPIRE_HOURS = 1; // 数据过期时间（1小时）
    private final String WEATHER_CACHE_KEY = "province_weather_data";

    /**
     * 获取所有省份天气信息（自动更新过期数据）
     */
    public List<ProvinceWeather> getAllProvinceWeather() {
        try {
            // 1. 先从Redis缓存中获取数据
            List<ProvinceWeather> cachedWeather = (List<ProvinceWeather>) redisUtil.get(WEATHER_CACHE_KEY);
            if (cachedWeather != null && !cachedWeather.isEmpty()) {
                return cachedWeather;
            }
            
            // 2. Redis中没有缓存数据，查询数据库
            List<ProvinceWeather> allWeather = weatherMapper.selectList(null);
            if (allWeather.isEmpty()) {
                // 数据库为空，直接全量更新
                updateAllProvinceWeather();
                return weatherMapper.selectList(null);
            }

            // 3. 检查是否需要更新（取最新一条数据的更新时间判断）
            ProvinceWeather latest = weatherMapper.selectOne(
                    new QueryWrapper<ProvinceWeather>().orderByDesc("update_time").last("LIMIT 1")
            );
            
            // 如果获取不到最新记录，直接返回现有数据
            if (latest == null || latest.getUpdateTime() == null) {
                // 将数据存入Redis缓存，设置过期时间30分钟
                redisUtil.set(WEATHER_CACHE_KEY, allWeather, 1800);
                return allWeather;
            }
            
            long diffHours = ChronoUnit.HOURS.between(latest.getUpdateTime(), LocalDateTime.now());
            log.debug("最新数据更新时间：" + latest.getUpdateTime() + "，距离现在 " + diffHours + " 小时");

            // 4. 数据过期（超过1小时），触发异步更新并返回旧数据
            if (diffHours >= EXPIRE_HOURS) {
                log.debug("天气数据已过期，开始异步更新...");
                // 异步更新数据，不阻塞当前请求
                new Thread(this::updateAllProvinceWeather).start();
            }

            // 5. 将数据存入Redis缓存，设置过期时间30分钟
            redisUtil.set(WEATHER_CACHE_KEY, allWeather, 1800);
            
            // 6. 直接返回现有数据（无论是旧数据还是刚更新的数据都会返回）
            return allWeather;
        } catch (Exception e) {
            // 出现任何异常都返回空列表，避免服务不可用
            log.error("获取所有省份天气信息失败：" + e.getMessage());
            return new ArrayList<>();
        }
    }

    /**
     * 全量更新所有省份天气（调用高德API，处理QPS限制）
     */
    private void updateAllProvinceWeather() {
        // 1. 获取所有省份列表（从数据库查询，避免硬编码）
        List<ProvinceWeather> provinces = weatherMapper.selectList(null);
        List<ProvinceWeather> updateList = new ArrayList<>();

        // 2. 逐个调用高德API（控制QPS：每500ms请求1次，确保1s≤2次）
        for (ProvinceWeather province : provinces) {
            try {
                // 调用高德天气API
                String url = String.format(
                        "https://restapi.amap.com/v3/weather/weatherInfo?city=%d&key=%s&extensions=base",
                        province.getCode(), GAODE_KEY
                );
                String response = restTemplate.getForObject(url, String.class);
                JsonNode root = objectMapper.readTree(response);

                // 解析返回结果
                if ("1".equals(root.get("status").asText())) {
                    JsonNode lives = root.get("lives").get(0);
                    ProvinceWeather update = new ProvinceWeather();
                    update.setProvince(province.getProvince());
                    update.setWeather(lives.get("weather").asText());
                    update.setTemperatureFloat(new BigDecimal(lives.get("temperature").asText()));
                    update.setHumidityFloat(new BigDecimal(lives.get("humidity").asText()));
                    updateList.add(update);
                }

                // 控制QPS：每500ms请求1次
                Thread.sleep(500);
            } catch (Exception e) {
                System.err.println("更新" + province.getProvince() + "天气失败：" + e.getMessage());
            }
        }

        // 3. 批量更新数据库
        if (!updateList.isEmpty()) {
            weatherMapper.batchUpdateByProvince(updateList);
            
            // 4. 清除Redis缓存，下次请求时会重新加载最新数据
            redisUtil.del(WEATHER_CACHE_KEY);
        }
    }
}